#if !defined(SM__CONFIG_H)
#define SM__CONFIG_H

#include <string>
#include <map>
#include <vector>
#include <list>
#include <iostream>

struct XMLNode;

typedef std::vector<XMLNode*> NodeArray;
typedef std::map<std::string,std::string>::iterator AttrIter;
typedef std::vector<XMLNode*>::iterator NodeIter;

// API
XMLNode* loadConfig(const char* szConfigFilename);
bool saveConfig(XMLNode* rootNode, const char* szConfigFilename);
void serializeXMLNode(std::ostream& os, XMLNode* node);

// TODO:  Preserve XML processing instructions...

// For the XML entity <sprite id="blah" />, we have an XMLNode where
// - tagName = "sprite"
// - attr["id"] = "blah"
struct XMLNode {
  std::string tagName;  
  std::map<std::string,std::string> attr; 
  std::vector<XMLNode*> children; // this can be nodes XML elements or text nodes, use DOM methods below
  XMLNode* parentNode;
  std::string textContent;
    
  XMLNode();
  // deletes the children nodes
  ~XMLNode();

  const std::string& id();

  // ======================================================================= //
  // DOM Methods
  // ======================================================================= //

  // finds the first element matching the input ID
  // returns NULL if no element found
  XMLNode* getElementById(const char* elemID);

  // returns the first element matching the tag name
  XMLNode* getElementByTagName(const char* _tagName);

  // if outArr is not NULL, this function appends all matching elements to outArr 
  // returns the number of elements found of that tagname
  int getElementsByTagName(const char* _tagName, NodeArray* outArr);

  bool hasChildNodes() const;
  // ======================================================================= //
};

// helper macros
#define ATOI(inStr) atoi(inStr.c_str())
#define ATOF(inStr) atof(inStr.c_str())

#endif // SM__CONFIG_H
